Lukas Krenz, Mathias Wagner, Sr. Developer Technology Engineer
| S72978 | GTC 2025
超级芯片的构建模块
高性能高能效核心
快速片上互联结构
高带宽低功耗内存
一致性的芯片间连接
业界领先的每瓦性能
复用他人的工作
首先把基础工作做好:
仅当上述步骤失败时:
这些步骤中的每一步都应涉及验证正确性,并且应由数据驱动。
使用标志 -O3 -mcpu=native -ffp-contract=fast
-mcpu=neoverse-v2+crypto+sha3+sm4+sve2-aes+sve2-sha3+sve2-sm4 标志会启用所有功能(可能不检测加密扩展)。-Ofast,但在移植前请务必检查其准确性。-ffp-contract=off 来禁用浮点运算收缩(例如,FMA)。使用 -flto 来启用链接时优化。
Grace 受益于代码局部性:考虑使用配置文件引导优化(Profile-Guided Optimization)。
-fsigned-char 或 -funsigned-char,具体取决于开发者的假设。-fno-stack-arrays 中受益。使用默认接口以实现性能可移植性
优先使用 Netlib BLAS/LAPACK 和 FFTW 接口。
NVPL (https://developer.nvidia.com/nvpl)
ArmPL (https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Libraries)
了解您的硬件
了解您的代码
了解您的工具
获得一个可靠的基线性能(可复现)。
Uncore 事件:涵盖核心之外发生的所有事情,在套接字(socket)级别收集。
Arm 统计性能分析扩展(Arm Statistical Profiling Extension, SPE)
更多详情请参考 NVIDIA Grace 调优指南和 Arm Neoverse V2 PMU 指南 (https://developer.arm.com/documentation/109709/latest/)。
NVIDIA 开发了 NVIDIA Nsight Systems:
开源工具,例如:
Linaro MAP:专注于并行代码的商业性能分析器。
在不计算过多事件时开销极低
测量平均频率(周期/时间)、IPC(指令/周期)、分支未命中等。
$ perf stat -I 100 -o perf.json --json \
-e 'duration_time,{nvidia_scf_pmu_0/cmem_rd_data/,nvidia_scf_pmu_0/cmem_wr_total_bytes/}'
(32 * cmem_rd_data + cmem_wr_total_bytes) / duration_time / 1e9时间线视图
Nsight Systems 文档
https://docs.nvidia.com/nsight-systems/UserGuide/index.html
为离线时间线收集性能数据
nsys profile ./app在 Nsight Systems 中打开生成的 *.nsys-rep 文件。
标记您的代码
#include <nvtx3/nvToolsExt.h>
void congrad_64()
{
nvtxRangePush(__func__); // Range around the whole function
for (int i = 0; i < 6; ++i)
{
nvtxRangePush("loop range"); // Range for iteration
// Do ab iteration
nvtxRangePop(); // End the inner range
}
nvtxRangePop(); // End the outer range
}
收集核心性能指标
使用以下命令查看可用的核心指标:
nsys profile --cpu-core-metrics=help
收集 uncore 性能指标
使用以下命令查看可用的套接字(socket)级别指标:
nsys profile --cpu-socket-metrics=help
链接:https://github.com/brendangregg/FlameGraph
使用 Nsight Systems
Scripts/Flamegraph 目录中nsys profile -o report ./apppython3 stackcollapse_nsys.py report.nsys-rep | ./flamegraph.pl > result_flamegraph.svg使用 perf
perf record -a -g ./appperf script | stackcollapse-perf.pl > out.perf-foldedflamegraph.pl out.perf-folded > perf.svg该工具可以帮助开发者理解编译器对源代码所做的具体优化和转换,通过并排显示源代码、生成的汇编代码以及编译器优化后的代码,可以直观地看到向量化等优化的效果。
代码来自 Coral 基准测试套件的 HACCmk 基准测试,来源:https://asc.llnl.gov/coral-benchmarks
请按顺序遵循这些建议,例如,优先选择自动向量化而不是内联函数(intrinsics)。
编译器 (Compilers)
#pragma omp parallel for simd#pragma vector always库 (Libraries)
内联函数 (Intrinsics - ACLE)
汇编 (Assembly)
通常在较高的优化级别下启用。
-Ofast (例如,归约操作)。诊断标志可以让你看到编译器做了什么以及没有向量化的部分。
LLVM:
-Rpass(-missed|-analysis)=loop-vectorizeGCC:
-fopt-info-vec-(optimized|missed|all|note)NVIDIA compilers:
-Minfo=vect查看输出和生成的代码 → 使用 Compiler explorer / Godbolt。
在适用的情况下,在 C / C++ 中使用 restrict 指针。
使用 pragmas 来指导编译器(取决于所使用的编译器)。
#pragma GCC ivdep#pragma clang loop vectorize#pragma omp simdArm 的内存模型是弱序 (weakly-ordered) 的,与 x86 的内存模型不同:加载/存储操作可能在运行时被 CPU 重排。
写入操作对其他线程的可见顺序可能不同。
许多程序使用顺序一致性 (sequential consistency) 来在线程间传递消息 (例如, std::atomic with std::memory_order_seq_cst)。
对于线程间的同步,release/acquire 语义可能就足够了。
使用较弱的内存顺序可以提高性能,但也可能引入错误。
如果不确定:请使用库中的同步原语。
这是一个复杂的话题,更多上下文请参考 Herb Sutter 的文章:https://herbsutter.com/2013/02/11/atomic-weapons-the-c-memory-model-and-modern-hardware/
主要 takeaways
首先把基础工作做好。
使用数据驱动的迭代优化工作流。
使用性能分析工具。
理解你的性能预期和瓶颈。
也欢迎访问我们今天下午 3:00 – 3:50 PM 的 CWE:
如何在 NVIDIA Grace CPU 上运行和优化您的工作负载 [CWE73338]